import aiohttp
import asyncio
from typing import Dict, Any, Optional

from api.xbot.xbot_base_api import XbotBaseApi
from common.config_manager import ConfigManager, ApiConfig, config_manager


class FriendApi(XbotBaseApi):
    # ==================== Friend 好友模块 ====================
    async def friend_get_contract_list(self, current_wxcontact_seq: int = 0, current_chat_room_contact_seq: int = 0, timeout: int = 30, retries: int = 3):
        """获取通讯录好友列表"""
        body = {
            "Wxid": self.wx_id,
            "CurrentWxcontactSeq": current_wxcontact_seq,
            "CurrentChatRoomContactSeq": current_chat_room_contact_seq
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/GetContractList",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_get_contract_detail(self, towxids: str, chat_room: str = "", timeout: int = 30, retries: int = 3):
        """获取通讯录好友详情 - towxids必须是逗号分隔的字符串，最多20个"""
        body = {
            "Wxid": self.wx_id,
            "Towxids": towxids,  # 多个微信ID用英文逗号隔开，最多20个
            "ChatRoom": chat_room
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/GetContractDetail",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_search(self, to_user_name: str, from_scene: int = 0, search_scene: int = 1, timeout: int = 30, retries: int = 3):
        """搜索联系人"""
        body = {
            "Wxid": self.wx_id,
            "ToUserName": to_user_name,
            "FromScene": from_scene,
            "SearchScene": search_scene
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/Search",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_send_request(self, v1: str, v2: str, scene: int = 0, opcode: int = 1, verify_content: str = "", timeout: int = 30, retries: int = 3):
        """添加联系人(发送好友请求)"""
        body = {
            "Wxid": self.wx_id,
            "V1": v1,
            "V2": v2,
            "Scene": scene,
            "Opcode": opcode,
            "VerifyContent": verify_content
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/SendRequest",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_set_remarks(self, to_wxid: str, remarks: str, timeout: int = 30, retries: int = 3):
        """设置好友备注"""
        body = {
            "Wxid": self.wx_id,
            "ToWxid": to_wxid,
            "Remarks": remarks
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/SetRemarks",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_delete(self, to_wxid: str, timeout: int = 30, retries: int = 3):
        """删除好友"""
        body = {
            "Wxid": self.wx_id,
            "ToWxid": to_wxid
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/Delete",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_blacklist(self, to_wxid: str, val: int, timeout: int = 30, retries: int = 3):
        """添加/移除黑名单 - Val == 15添加 7移除"""
        body = {
            "Wxid": self.wx_id,
            "ToWxid": to_wxid,
            "Val": val
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/Blacklist",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_get_friendstate(self, username: str, timeout: int = 30, retries: int = 3):
        """查询好友状态"""
        body = {
            "Wxid": self.wx_id,
            "UserName": username
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/GetFriendstate",
            body,
            timeout=timeout,
            retries=retries
        )

    async def friend_pass_verify(self, v1: str, v2: str, scene: int, timeout: int = 30, retries: int = 3):
        """通过好友请求"""
        body = {
            "Wxid": self.wx_id,
            "V1": v1,
            "V2": v2,
            "Scene": scene
        }
        return await self._make_request_with_retry(
            f"{self.base_url}/Friend/PassVerify",
            body,
            timeout=timeout,
            retries=retries
        )
        
    async def _make_request_with_retry(self, url: str, body: Dict[str, Any], timeout: int = 30, retries: int = 3) -> Dict[str, Any]:
        """带有重试机制的API请求"""
        last_exception = None
        for attempt in range(retries):
            try:
                timeout_obj = aiohttp.ClientTimeout(total=timeout)
                async with aiohttp.ClientSession(timeout=timeout_obj) as session:
                    async with session.post(url, json=body) as response:
                        return await response.json()
            except (aiohttp.ClientError, asyncio.TimeoutError, ConnectionError) as e:
                last_exception = e
                if attempt < retries - 1:  # 不是最后一次尝试
                    # 指数退避策略
                    wait_time = 0.5 * (2 ** attempt)  # 0.5, 1, 2, 4, 8...
                    print(f"请求失败，{wait_time}秒后重试 ({attempt+1}/{retries}): {str(e)}")
                    await asyncio.sleep(wait_time)
                else:
                    print(f"请求失败，已达到最大重试次数 ({retries}): {str(e)}")
        
        # 所有重试都失败了，返回错误响应
        return {
            "Success": False,
            "Code": -1,
            "Message": f"请求失败，网络错误: {str(last_exception)}",
            "Data": None
        }